<template>
  <div class="draw-box">
    <div :id="'box_player_'+ id" class="box-player" v-loading="loading">
      <img v-show="!isVideo" class="player" :src="imgUrl">
      <EasyPlayer v-show="isVideo" class="player" ref="pleyer" :videoUrl="videoUrl" live :easyStretch="true" :reconnection="true" :has-audio="false" @playing="playing" alt=""></EasyPlayer>
      <el-select v-if="isVideo && protocolTypeOptions.length" class="protocol-switch" v-model="protocolType" title="切换视频流协议类型" :popper-append-to-body="false" @change="getVideo">
        <el-option v-for="item in protocolTypeOptions" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue"></el-option>
      </el-select>
      <i class="full iconfont" :class="isScreenFull ? 'icon-caozuo-quanping-shousuo1' : 'icon-caozuo-quanping-zhankai1'" @click="doFull"></i>
      <DrawArea ref="drawArea" :data="data" :draw="draw" :btns="drawBtns" :expand="expand" :unDraw="unDraw" v-bind="$attrs" v-on="{...$listeners, doSave: goSave}"></DrawArea>
      <div class="error-msg" :class="isVideo ? 'video-error' : 'img-error'">{{ errorMsg }}</div>
    </div>
  </div>
</template>
<script>
/* 引入全局js */
import DrawArea from '@/components/canvas/drawArea';
import defaultImg from '@/assets/image/img-error.png';
import {getPresetImg, imgUpload} from '@/api/modules/configManagemnet/algorithmConfigAdd';
import {getVideoRealtimeUrl} from '@/api/video/video';
import store from "@/store";

export default {
  components: {
    DrawArea
  },
  props: {
    data: { //数据信息, deviceCode: 设备编码, channelCode: 通道编码, presetId: 预置位id, posType: 算法归属(1: 通道, 2: 预置位)
      type: Object,
      default: () => ({})
    },
    draw: { //组件类型, undefined: 只查看, false: 查看可点击, true: 编辑
      default: undefined
    },
    btns: { //标绘编辑按钮列表, 1: 识别区域, 2: 定位, 3: 图斑, 4: 屏蔽区域, 5: 拌线, 6: 暂存, 7: 清除
      type: Array,
      default: () => ([])
    },
    isVideo: { //是否实时视频
      default: false
    },
    expand: { //扩展功能,支持同时多种, 1: 关联算法, 2: 自动暂存, 3: 图斑管理新增, 4: 图斑管理修改
      type: Array,
      default: () => ([])
    },
    mapBtns: { //地图按钮权限, 1: 定位按钮, 2: 图斑按钮, 3: 抓图按钮
      default: () => ([1, 2])
    },
  },
  data() {
    return {
      id: this.getUUID(),
      imgUrl: defaultImg, //图片地址
      videoUrl: '', //视频地址
      errorMsg: '', //错误信息
      loading: false, //加载动画
      protocolType: store.getters.protocolTypeNew, //流协议类型
      protocolTypeOptions: [], ////流协议类型列表
      isScreenFull: false, //是否全屏
      lastRequest: 0, //匹配最后一次请求
      drawBtns: [], //标绘编辑按钮列表
      unDraw: false, //不能标绘提示文字
      editImg: undefined, //编辑使用图片
      dataNew: false
    };
  },
  watch: {
    /**
     * 地图按钮权限
     */
    mapBtns: {
      handler: function() {
        this.checkBtns();
      },
      immediate: true
    },
    /**
     * 监听标绘编辑按钮列表
     */
    btns: {
      handler: function() {
        this.checkBtns();
      },
      immediate: true
    },
    /**
     * 监听是否实时视频切换
     */
    isVideo: {
      handler: function(val) {
        this.checkBtns();
        this.imgVideoChange();
      },
      immediate: true
    },
    /**
     * 数据信息 查询图片
     */
    data: {
      handler: function(n) {
        this.checkBtns();
        this.getImg();
        if(n?.deviceCode !== this.dataNew?.deviceCode || n?.channelCode !== this.dataNew?.channelCode) {
          this.getVideo();
        }
        this.dataNew = JSON.parse(JSON.stringify(n));
      },
      immediate: true,
      deep: true
    }
  },
  beforeDestroy() {
    if(this.resizeObserver) {
      this.resizeObserver.disconnect();
    }
    clearTimeout(this.timing);
  },
  mounted() {
    this.resizeScreen();
    this.initDicts();
  },
  methods: {
    /**
     * 实时视频播放成功回调
     */
    playing(e) {
      console.log('%c 实时视频播放成功==', 'color: blue', e)
    },
    /**
     * 校验按钮
     */
    checkBtns() {
      this.drawBtns = JSON.parse(JSON.stringify(this.btns));
      if(!this.isVideo && String(this.data.posType) === '1') {
        this.drawBtns = [];
        if(this.btns.includes(6)) {
          this.drawBtns.push(6);
        }
      }
      if(!this.mapBtns.includes(1) && this.drawBtns.includes(2)) {
        this.drawBtns.splice(this.drawBtns.indexOf(2), 1);
      }
      if(!this.mapBtns.includes(2) && this.drawBtns.includes(3)) {
        this.drawBtns.splice(this.drawBtns.indexOf(3), 1);
      }
    },
    /**
     * 标绘传数据到地图
     */
    doDrawToMap({type, status, info, draws} = {}) {
      this.$parent.doDrawToMap({type, status, info, draws});
    },
    /**
     * 标绘回填
     */
    doDrawBack(draw, append, select) {
      this.$refs.drawArea.doDrawBack(draw, append, select);
    },
    /**
     * 标绘还原颜色
     */
    restoreColor(){
      this.$refs.drawArea.restoreColor();
    },
    /**
     * 地图传数据到标绘
     */
    doMapToDraw({info} = {}) {
      this.$refs.drawArea.doMapToDraw({info});
    },
    /**
     * 清除标绘
     */
    clearDraw() {
      this.$refs.drawArea.clearDraw();
    },
    /**
     * 选择标绘区域
     */
    doDrawChoose(id, select, call) {
      this.$refs.drawArea.doDrawChoose(id, select, call);
    },
    /**
     * 获取全部标绘
     */
    getAllDraw(type) {
      return this.$refs.drawArea.getAllDraw(type);
    },
    /**
     * 主动暂存
     */
    doSave(fn) {
      if(fn) {
        this.$refs.drawArea.doSave((list) => {
          this.goSave(null, (imgUrl) => {
            fn(list, imgUrl);
          })
        });
      }else {
        this.$refs.drawArea.doSave();
      }
    },
    /**
     * 标绘暂存回调
     */
    goSave(list, fn) {
      if(this.expand.includes(1)) {
        if(this.isVideo) {
          this.loading = true;
          this.screenshot((back) => {
            this.uploadImg(back.file, (imgUrl) => {
              this.loading = false;
              if(fn) {
                return fn(imgUrl);
              }
              this.$emit('doSave', list, imgUrl);
            });
          });
        }else {
          if(fn) {
            return fn(this.imgUrl);
          }
          this.$emit('doSave', list, this.imgUrl);
        }
      }else {
        if(fn) {
          return fn();
        }
        this.$emit('doSave', list);
      }
    },
    /**
     * 视频抓图
     */
    screenshot(fn) {
      const $dom = this.$refs['pleyer'];
      try{
        $dom.snapshot((back) => {
          fn && fn(back);
        });
      }catch(e){
        this.loading = false;
        $message.e('抓图失败');
      }
    },
    /**
     * 上传图片
     */
    uploadImg(file, fn) {
      const formData = new FormData();
      formData.append('file', file);
      imgUpload(formData).then((resp) => {
        if(resp.code === 200) {
          fn && fn(resp.data.fileUrl);
        }else {
          this.loading = false;
          this.$refs.drawArea.doMessTs(resp.msg, true);
        }
      }).catch(() => {
        this.loading = false;
        this.$refs.drawArea.doMessTs('上传图片失败', true);
      });
    },
    /**
     * 屏幕大小改变
     */
    resizeScreen() {
      this.checkScreenFull();
      this.resizeObserver  = new ResizeObserver(() => {
        clearTimeout(this.timing);
        this.timing = setTimeout(() => {
          this.checkScreenFull();
        }, 200);
      });
      this.resizeObserver.observe($('#box_player_'+ this.id)[0]);
    },
    /**
     * 初始化字典 99: 查询流协议类型列表
     */
    initDicts() {
      this.getMultipleDicts(['99']).then((response) => {
        this.protocolTypeOptions = response.data['99'] || [];
      });
    },
    /**
     * 切换图片、视频
     */
    imgVideoChange() {
      this.getImg();
      this.getVideo();
    },
    /**
     * 查询图片
     */
    getImg(img = this.editImg) {
      if(this.isVideo) {
        return false;
      }
      this.editImg = img;
      this.errorMsg = '';
      this.unDraw = '';
      this.videoUrl = '';
      this.imgUrl = defaultImg;
      if(this.editImg) {
        this.imgUrl = this.editImg;
        this.loading = false;
        return false;
      }
      if(!this.data.deviceCode || !this.data.channelCode) {
        return false;
      }
      if(String(this.data.posType) !== '1' && !this.data.presetId) {
        return false;
      }
      const lastRequest = this.lastRequest = Date.now();
      this.loading = true;
      getPresetImg(this.data).then((resp) => {
        if(this.lastRequest !== lastRequest) {
          return false;
        }
        this.loading = false;
        if(resp.code === 200) {
          this.imgUrl = resp.data.imgUrl;
        }else {
          this.checkImg();
        }
      }).catch(() => {
        this.loading = false;
        this.errorMsg = '图片查询失败';
      });
    },
    /**
     * 校验图片
     */
    checkImg() {
      if(this.expand.includes(1)) {
        if(this.draw && String(this.data.posType) === '1') {
          this.errorMsg = '您无需标绘，可直接点击暂存按钮完成通道算法配置后保存。如需进行标绘，请选择“实时标绘”后进行。';
          return false;
        }
        if(this.draw && String(this.data.posType) === '2' && this.data.presetId) {
          this.errorMsg = '获取预置位图片失败，如需再次获取，请在实时视频中重新编辑该预置位或通过实时标绘进行算法配置。';
          return false;
        }
      }
      if(this.expand.includes(2)) {
        if(!this.draw) {
          this.errorMsg = '暂无预置位图片，请点击“抓图”按钮获取最新预置位图片。';
        }else {
          this.unDraw = this.errorMsg = '暂无预置位图片，请点击“抓图”按钮获取最新预置位图片或者切换到实时标绘。';
        }
      }
    },
    /**
     * 查询视频
     */
    getVideo() {
      if(!this.isVideo) {
        return false;
      }
      this.errorMsg = '';
      this.unDraw = '';
      this.videoUrl = '';
      if(!this.data.deviceCode || !this.data.channelCode) {
        this.errorMsg = '未播放视频';
        return false;
      }
      const params = {
        deviceCode: this.data.deviceCode, //设备编码
        channelCode: this.data.channelCode, //通道编码
        streamType: 1, //码流类型 1-主码流；2-子码流；
        protocolType: this.protocolType, //协议类型 1-rtsp；2-rtmp；3-hls；4-http-flv； 5-wss；
        netType: store.getters.netType
      };
      const lastRequest = this.lastRequest = Date.now();
      this.loading = true;
      getVideoRealtimeUrl(params).then((resp) => {
        if(this.lastRequest !== lastRequest) {
          return false;
        }
        this.loading = false;
        if(resp.code === 200) {
          this.videoUrl = resp.data.streamUrl;
        }else {
					$message.a(resp);
          this.errorMsg = '视频查询失败';
        }
      }).catch(() => {
        this.loading = false;
        this.errorMsg = '视频查询失败';
      });
    },
    /**
     * 全屏
     */
    doFull() {
      this.checkScreenFull();
      if(this.isScreenFull) {
        this.outFullScreen();
      }else {
        let el = document.getElementById('box_player_'+ this.id) || document.documentElement;
        const rfs = el.requestFullScreen || el.webkitRequestFullScreen || el.mozRequestFullScreen || el.msRequestFullscreen;
        if (typeof rfs !== 'undefined' && rfs) {
          rfs.call(el);
        }
      }
    },
    /**
     * 退出全屏
     */
    outFullScreen() {
      let fullscreenEnabled = document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled;
      if (!fullscreenEnabled) {
        return false;
      }
      let fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement;
      if(fullscreenElement !== undefined) {
        if (document.exitFullscreen) {
          document.exitFullscreen();
          return false;
        }
        if (document.msExitFullscreen) {
          document.msExitFullscreen();
          return false;
        }
        if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen();
          return false;
        }
        if (document.webkitExitFullscreen) {
          document.webkitExitFullscreen();
        }
      }
    },
    /**
     * 校验是否全屏
     */
    checkScreenFull() {
      const a = document.mozFullScreen || document.fullScreen || document.webkitIsFullScreen;
      const b = document.webkitRequestFullScreen || document.mozRequestFullScreen || document.msFullscreenEnabled;
      this.isScreenFull = a || b;
    },
    /**
     * 生成uuid
     */
    getUUID() {
      const crypto = window.crypto || window.msCrypto;
      const array = new Uint32Array(1);
      const r = crypto.getRandomValues(array)[0] ;
      return Date.now() + '666' + r;
    }
  },
}
</script>

<style lang="scss" scoped>
  .draw-box{
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    z-index: 19;
    background: #fff;
    cursor: default;
    overflow: hidden;
    .box-player{
      height: 100%;
      max-width: 100%;
      aspect-ratio: 16/9;
      margin: 0 auto;
      position: relative;
      .player{
        display: block;
        height: 100%;
        width: 100%;
        pointer-events: none;
        /deep/ .vjs-control-bar, /deep/ .vjs-big-play-button{
          display: none !important;
        }
        /deep/ .easy-player-loading{
          img {
            content: url("~@/assets/image/logo-gif.gif") !important;
            width: 100% !important;
            height: auto !important;
          }
          .loading-text{display: none !important;}
        }
        /deep/ .video-js{
          background: none !important;
        }
      }
      .protocol-switch{
        width: 78px;
        height: 32px;
        background: rgba(255, 106, 108, 0.6);
        border-radius: 3px;
        position: absolute;
        top: 18px;
        left: 18px;
        z-index: 100;
        /deep/ .el-input__inner{
          background: none;
          border: 0;
          color: #fff;
          font-size: 16px;
        }
        /deep/ .el-select__caret{
          color: #fff;
        }
      }
      .full{
        display: block;
        width: 30px;
        height: 30px;
        line-height: 30px;
        text-align: center;
        background: rgba(0, 0, 0, 0.4);
        border-radius: 4px;
        position: absolute;
        top: 18px;
        right: 18px;
        z-index: 100;
        color: #fff;
        font-size: 16px;
        cursor: pointer;
      }
      .error-msg{
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        height: 100%;
        position: absolute;
        top: 0;
        left: 0;
        pointer-events: none;
        padding: 0 20px;
        font-size: 16px;
        &.video-error{
          color: #fff;
        }
        &.img-error{
          color: #999;
        }
      }
    }
  }
</style>
<style lang="scss">

</style>
